package com.njtoyo.taxi.admin.rest.controller.business;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njtoyo.taxi.admin.aop.PassToken;
import com.njtoyo.taxi.admin.aop.PermissionScope;
import com.njtoyo.taxi.admin.mapper.master.entity.DriverWithdraw;
import com.njtoyo.taxi.admin.mapper.master.enums.DriverWithdrawState;
import com.njtoyo.taxi.admin.rest.presenter.business.driver_withdraw.DriverWithdrawListPresenter;
import com.njtoyo.taxi.admin.rest.presenter.business.driver_withdraw.DriverWithdrawStatisticsPresenter;
import com.njtoyo.taxi.admin.rest.presenter.platfrom.AdminUserIdentityPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.business.driver.UpdatePlateNumberWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.business.driver_withdraw.IndexWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.business.driver_withdraw.UpdateBankInfoWrapper;
import com.njtoyo.taxi.admin.service.business.DriverWithdrawService;
import com.njtoyo.taxi.entity.backend.AdminUser;
import com.taxi.entity.common.RestResult;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("finance/driver-withdraw")
@RequiredArgsConstructor
@Slf4j
public class DriverWithdrawController {
    private final DriverWithdrawService driverWithdrawService;

    @GetMapping
    public RestResult<Page<DriverWithdrawListPresenter>> index(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, IndexWrapper wrapper) {
        return driverWithdrawService.getPage(adminUser, wrapper);
    }

    @GetMapping("/{id}/actions")
    public RestResult<?> getActions(@PathVariable("id") Long id) {
        return driverWithdrawService.getActions(id);
    }

    @PostMapping("/pay/{ids}")
    public RestResult<?> doPay(@PathVariable("ids") String ids) {
        return driverWithdrawService.doPay(ids);
    }

    @GetMapping("export")
    public void export(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, IndexWrapper wrapper, HttpServletResponse response) throws IOException {
        driverWithdrawService.export(adminUser, wrapper, response);
    }

    @PatchMapping("/{id}/update/bankinfo")
    @ApiOperation(value = "修改银行信息")
    RestResult updatePlateNumber(@PathVariable("id") Long id, @RequestBody UpdateBankInfoWrapper updateBankInfoWrapper) {
        return driverWithdrawService.updateBankInfo(updateBankInfoWrapper);
    }

    /**
     * 批量打款
     *
     * @return
     */
    @PostMapping("/remit/{id}")
    RestResult remitById(@PathVariable("id") Long id) {
        Date now = DateUtil.date();
        int nowHour = DateUtil.hour(now, true);
//        if (8 > nowHour || nowHour > 22) {
//            return RestResult.failed("此时间段银行不支持打款操作");
//        }
        log.info("执行单个提现记录打款，ID：{}", id);
        if (id == null) {
            return RestResult.failed("id不能为空");
        }
        return driverWithdrawService.remit(id);
    }


    @PostMapping("/remoteRemitById/{id}")
    @PassToken
    RestResult remoteRemitById(@PathVariable("id") Long id, HttpServletRequest request) {
        String clientIP = ServletUtil.getClientIP(request);
//        if (!clientIP.contains("192.168.2")) {
//            return RestResult.failed("IP错误");
//        }
        log.info("执行单个提现记录打款，ID：{}", id);
        if (id == null) {
            return RestResult.failed("id不能为空");
        }
        return driverWithdrawService.remit(id);
    }


    /**
     * 批量打款
     *
     * @return
     */
    @PostMapping("/batchRemit")
    @ApiOperation(value = "批量打款")
    RestResult batchRemit() {
        Date now = DateUtil.date();
        int nowHour = DateUtil.hour(now, true);
        if (8 > nowHour || nowHour > 22) {
            return RestResult.failed("此时间段银行不支持打款操作");
        }
        log.info("执行批量打款操作");
        return driverWithdrawService.remit(null);
    }


    @GetMapping("/statistics")
    RestResult statistics(@ModelAttribute("admin") AdminUser adminUser) {
        List<DriverWithdraw> list = driverWithdrawService.list();

        DriverWithdrawStatisticsPresenter statisticsPresenter = new DriverWithdrawStatisticsPresenter();
        AdminUserIdentityPresenter identity = (AdminUserIdentityPresenter) adminUser.getIdentity();
        if (CollUtil.isNotEmpty(list)) {
            List<DriverWithdraw> result = new ArrayList<>();
            result = list;
            List<Long> drivers = new ArrayList<>();
            switch (adminUser.getAccountType()) {
                case company:
                    drivers = driverWithdrawService.getDriverIds(null, identity.getCompanyIds());
                    if(CollectionUtils.isNotEmpty(drivers)){
                        List<Long> finalDrivers = drivers;
                        List<DriverWithdraw> collect = list.stream().filter(item -> finalDrivers.contains(item.getId())).collect(Collectors.toList());
                        result = collect;
                    }else{
                        result = new ArrayList<>();
                    }
                    break;
                case canton:
                    drivers = driverWithdrawService.getDriverIds(identity.getCantonIds(), null);
                    if(CollectionUtils.isNotEmpty(drivers)){
                        List<Long> finalDrivers = drivers;
                        List<DriverWithdraw> collect = list.stream().filter(item -> finalDrivers.contains(item.getId())).collect(Collectors.toList());
                        result = collect;
                    }else{
                        result = new ArrayList<>();
                    }
                    break;
            }
            if(CollUtil.isNotEmpty(result)) {
                List<DriverWithdraw> newList = result.stream().filter(entity -> ObjectUtil.isNotNull(entity.getState())).collect(Collectors.toList());
                List<DriverWithdraw> initList = newList.stream().filter(entity -> entity.getState() == DriverWithdrawState.init).collect(Collectors.toList());
                BigDecimal initAmount = CollUtil.isNotEmpty(initList) ? initList.stream().map(DriverWithdraw::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add) : BigDecimal.ZERO;
                List<DriverWithdraw> operatedList = newList.stream().filter(entity -> entity.getState() == DriverWithdrawState.operated).collect(Collectors.toList());
                BigDecimal operatedAmount = CollUtil.isNotEmpty(operatedList) ? operatedList.stream().map(DriverWithdraw::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add) : BigDecimal.ZERO;
                List<DriverWithdraw> cancelledList = newList.stream().filter(entity -> entity.getState() == DriverWithdrawState.cancelled).collect(Collectors.toList());
                List<DriverWithdraw> failedList = newList.stream().filter(entity -> entity.getState() == DriverWithdrawState.failed).collect(Collectors.toList());


                statisticsPresenter.setInitCount(CollUtil.isNotEmpty(initList) ? initList.size() : 0);
                statisticsPresenter.setOperatedCount(CollUtil.isNotEmpty(operatedList) ? operatedList.size() : 0);
                statisticsPresenter.setCancelledCount(CollUtil.isNotEmpty(cancelledList) ? cancelledList.size() : 0);
                statisticsPresenter.setFailedCount(CollUtil.isNotEmpty(failedList) ? failedList.size() : 0);
                statisticsPresenter.setInitAmount(initAmount);
                statisticsPresenter.setOperatedAmount(operatedAmount);
            }
        }

        List<DriverWithdraw> listSuccess = driverWithdrawService.list(Wrappers.<DriverWithdraw>lambdaQuery()
                .between(DriverWithdraw::getWithdrawTime, DateUtil.beginOfDay(DateUtil.date()), DateUtil.endOfDay(DateUtil.date()))
                .eq(DriverWithdraw::getState, DriverWithdrawState.done));
        if (CollUtil.isNotEmpty(listSuccess)) {
            List<DriverWithdraw> result2 = listSuccess;
            List<Long> driverIds = new ArrayList<>();
            switch (adminUser.getAccountType()) {
                case company:
                    driverIds = driverWithdrawService.getDriverIds(null, identity.getCompanyIds());
                    if(CollectionUtils.isNotEmpty(driverIds)){
                        List<Long> finalDrivers = driverIds;
                        List<DriverWithdraw> collect = listSuccess.stream().filter(item -> finalDrivers.contains(item.getId())).collect(Collectors.toList());
                        result2 = collect;
                    }else{
                        result2 = new ArrayList<>();
                    }
                    break;
                case canton:
                    driverIds = driverWithdrawService.getDriverIds(identity.getCantonIds(), null);
                    if(CollectionUtils.isNotEmpty(driverIds)){
                        List<Long> finalDrivers = driverIds;
                        List<DriverWithdraw> collect = listSuccess.stream().filter(item -> finalDrivers.contains(item.getId())).collect(Collectors.toList());
                        result2 = collect;
                    }else{
                        result2 = new ArrayList<>();
                    }
                    break;
            }
            BigDecimal successAmount = result2.stream().map(DriverWithdraw::getAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
            statisticsPresenter.setTodaySuccessAmount(successAmount);
            statisticsPresenter.setTodaySuccessCount(result2.size());

        }


        return RestResult.success(statisticsPresenter);
    }

    @GetMapping("/remitHistory/{id}")
    @ApiOperation(value = "打款历史")
    RestResult remitHistory(@PathVariable("id") Long id) {
        return driverWithdrawService.remitHistory(id);
    }


    /**
     * 下载回执单
     *
     * @param id
     * @return
     */
    @GetMapping("/receiptFileDownload/{id}")
    RestResult receiptFileDownload(@PathVariable("id") Long id) {
        return driverWithdrawService.receiptFileDownload(id);
    }


    /**
     * @param id
     * @return
     */
    @DeleteMapping("/delete/{id}")
    RestResult deleteById(@PathVariable("id") Long id) {
        return driverWithdrawService.deleteById(id);
    }


    /**
     * 自动提现金额
     *
     * @return
     */
    @GetMapping("/getAutoWithdrawAmount")
    RestResult getAutoWithdrawAmount() {
        return driverWithdrawService.getAutoWithdrawAmount();
    }

    @PostMapping("/updateAutoWithdrawAmount")
    RestResult updateAutoWithdrawAmount(@RequestBody Dict dict) {
        String amount = MapUtil.getStr(dict, "amount");
        return driverWithdrawService.updateAutoWithdrawAmount(amount);
    }


}
